package com.msgc.utils.crypto.asymmetric;

import com.msgc.utils.crypto.asymmetric.exception.AsymmetricCryptoException;
import com.msgc.utils.crypto.asymmetric.exception.KeyPairException;
import com.msgc.utils.crypto.asymmetric.processor.AsymmetricCryptoProcessor;
import org.apache.commons.lang3.StringUtils;
import org.apache.xerces.impl.dv.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * RSA 的加解密以及签名工具实现：用于与前端交互。填充方式为 jdk 默认（RSA/None/PKCS1Padding）
 * @author liuyanming 2019/12/18
 */
@Service
public class AsymmetricCryptoServiceImpl implements AsymmetricCryptoService {

	private static final Logger log = LoggerFactory.getLogger(AsymmetricCryptoServiceImpl.class);

	/** 非对称加密处理器 */
	private final AsymmetricCryptoProcessor processor;

	/** 秘钥 id ：用于获取加解密的公钥私钥对。分布式时无需关心其他组件是否会有冲突 */
	private final String keySymbol = "keyId";

	@Autowired
	public AsymmetricCryptoServiceImpl(AsymmetricCryptoProcessor processor) {
		this.processor = processor;
		try {
			this.processor.buildKeyPair(keySymbol);
		} catch (Exception e) {
			log.error("asymmetric init fail");
			throw new RuntimeException(e);
		}
	}

	@Override
	public String getPublicKey() throws KeyPairException {
		return processor.getPublicKeyString(keySymbol);
	}

	@Override
	public String decrypt(String cipher) throws AsymmetricCryptoException {
		if(StringUtils.isNotBlank(cipher)) {
			byte[] text = processor.decrypt(keySymbol, Base64.decode(cipher));
			return new String(text, CHARSET_UTF_8);
		}
		return cipher;
	}

	@Override
	public String encrypt(String text) throws AsymmetricCryptoException {
		if(StringUtils.isNotBlank(text)) {
			byte[] cipher = processor.encrypt(keySymbol, text.getBytes(CHARSET_UTF_8));
			return Base64.encode(cipher);
		}
		return text;
	}

	@Override
	public String encrypt(String text, String publicKey) throws AsymmetricCryptoException {
		if(StringUtils.isEmpty(publicKey)) {
			throw new NullPointerException("asymmetricEncrypt: publicKey is null!");
		}
		if(StringUtils.isEmpty(text)){
			return text;
		}
		byte[] cipher = processor.encrypt(text.getBytes(CHARSET_UTF_8), publicKey.getBytes());
		return Base64.encode(cipher);
	}

	@Override
	public String sign(String content) throws AsymmetricCryptoException {
		return new String(processor.sign(keySymbol, content.getBytes(CHARSET_UTF_8)), CHARSET_UTF_8);
	}

	@Override
	public boolean verify(String content, String signature) throws AsymmetricCryptoException {
		return processor.verify(keySymbol, content.getBytes(CHARSET_UTF_8), signature.getBytes(CHARSET_UTF_8));
	}

}
